# -*- coding: utf-8 -*-
from ws9 import line


ENDING_REPRS = {
    '\r': 'CR',
    '\r\n': 'CR/LF',
    '\n': 'LF',}


class Document(list):
    def __init__(self, string_in, tab_width=4):
        list.__init__(self,
            (line.Line(x, tab_width=tab_width)
                for x in string_in.splitlines(True)))
        self.tab_width = tab_width
    
    def __get_endings(self):
        ending_set = frozenset(line.ending for line in self if line.ending)
        if len(ending_set) == 1:
            return list(ending_set)[0]
        return ending_set
    
    def __set_endings(self, ending):
        if ending not in ['\r\n', '\r', '\n', '']:
            return
        for i in xrange(len(self)):
            self[i].ending = self[i].string_class(ending)
    
    def __del_endings(self):
        self.endings = '\n'
    
    def __get_indent_type(self):
        indent_set = frozenset(''.join(frozenset(line.indent_type))
            for line in self if line.indent)
        if len(indent_set) == 1:
            return list(indent_set)[0]
        return indent_set
    
    def __set_indent_type(self, indent_type):
        if indent_type == '':
            indent_type = ' '
        indent_type = ''.join(set(indent_type))
        if indent_type not in [' ', '\t']:
            return
        for i in xrange(len(self)):
            self[i].indent_type = indent_type
    
    def __del_indent_type(self):
        self.indent_type = ' '
    
    def __get_string_class(self):
        sc_set = frozenset(line.string_class for line in self)
        if len(sc_set) == 1:
            return list(sc_set)[0]
        return sc_set
    
    def __set_string_class(self, string_class):
        if string_class not in [str, unicode]:
            return
        line_class = line.STRING_TO_LINE[string_class]
        for i in xrange(len(self)):
            self[i] = line_class(self[i])
    
    def __del_string_class(self):
        self.string_class = str
    
    def __get_tab_width(self):
        tw_set = frozenset(line.tab_width for line in self)
        if len(tw_set) == 1:
            return list(tw_set)[0]
        return tw_set
    
    def __set_tab_width(self, tab_width):
        tab_width = int(tab_width)
        for i in xrange(len(self)):
            self[i].tab_width = tab_width
    
    def __del_tab_width(self):
        self.tab_width = 4
    
    def __repr__(self):
        return '<Document at %s (%s line endings, %s indentation)>' % (
            hex(id(self)),
            repr_endings(self.endings),
            repr_indents(self.indent_type))
    
    def __str__(self):
        return ''.join(str(line) for line in self)
    
    def __unicode__(self):
        return u''.join(unicode(line) for line in self)
    
    endings = property(__get_endings, __set_endings, __del_endings)
    indent_type = property(
        __get_indent_type, __set_indent_type, __del_indent_type)
    string_class = property(__get_string_class, __set_string_class,
        __del_string_class)
    tab_width = property(__get_tab_width, __set_tab_width, __del_tab_width)


def repr_endings(endings):
    endings_reprd = sorted(filter(bool,
        map(ENDING_REPRS.get, list(set(endings)))))
    if not endings_reprd:
        return 'No'
    return ', '.join(endings_reprd)


def repr_indents(indents):
    indents = set(indents)
    if indents == set(['\t', ' ']):
        return 'mixed'
    elif indents == set(['\t']):
        return 'tab'
    elif indents == set([' ']):
        return 'space'
    elif indents == set([]):
        return 'no'
    return 'unknown'
